#pragma once

#include <vector>
#include <deque>

#include "FixedSizeAllocator.h"

namespace MemMgr
{
	class SmallObjectAllocator
	{
	public:
		SmallObjectAllocator(size_t iPageSize, size_t iMaxObjectSize);
		~SmallObjectAllocator(){}
		void* Allocate(size_t iNumBytes);
		void Deallocate(void* iPtr, size_t iSize);
		bool Deallocate(void* iPtr);

		static SmallObjectAllocator& GetSingleton();
		static SmallObjectAllocator* GetSingletonPtr();

		size_t GetMaxObjectSize();

	private:

		SmallObjectAllocator(const SmallObjectAllocator& iOther); // Not implemented
		SmallObjectAllocator& operator=(const SmallObjectAllocator& iOther); // Not implemented

		inline AtomSizeU RetrieveId(const AtomSizeU iNumBytes) const;

		typedef AtomSizeU FixedSizeAllocatorId;
		typedef std::vector<FixedSizeAllocatorId> PoolId;
		typedef std::deque<FixedSizeAllocator> Pool;	// avoid reallocation on resize

		static const AtomSizeU MAX_ID_NUM = static_cast<AtomSizeU>(~0);

		PoolId mPoolId;
		Pool mPool;
		FixedSizeAllocatorId mLastDeallocatedIndex;
		size_t mPageSize;
		size_t mMaxObjectSize;
	};

	inline AtomSizeU SmallObjectAllocator::RetrieveId(const AtomSizeU iNumBytes) const
	{
		return iNumBytes - 1;
	}
}